const _variable = require('../../static/variable')
const wxp = require('../../static/wx.promise').default

const utils = require('./utils')
const Auth = require('./auth')

const config = require('../../static/config')

export let _ = utils

import Flyio from 'andy-flyio/dist/npm/wx'

const flyio = new Flyio()
flyio.interceptors.request.use(request => {
  // token create 接口不加token
  if (
    request.url.indexOf('common/token/create') > -1 ||
    request.url.indexOf('student/register') > -1 ||
    request.url.indexOf('check/student/identity') > -1 ||
    request.url.indexOf('check/student/registered') > -1
  ) {

    if (
      request.url.indexOf('common/token/create') > -1 ||
      request.url.indexOf('student/register') > -1
    ) {
      request.headers['auth-sys'] = 'student'
    }
    return request
  }
  let token = Auth.getToken()
  if (token) {
    request.headers['token'] = token
  } else {
    $global.showToast('没有token')
    let err =
      ['TOKEN_NOT_EXISTS_WHEN_REQUEST', new Error('token not exits')]
    console.logger && console.logger.error ?
      console.logger.error.apply(console, err) :
      console.error.apply(console, err)
  }
  return request
})

const {Request} = require('./request')

function genErr(res) {
  if (res && res.data && res.data.hasOwnProperty('msg')) {
    return new Error(res.data.msg ? res.data.msg : 'unknown error')
  }
  return new Error(res ? res.msg : 'unknown error')
}

class CommonRequest extends Request {
  constructor(...args) {
    super(...args)
    this.navigationBarLoading = false
    this.showLoading = true
    this.showError = true
    this.needHandleErr = true
    this._debug = false
  }

  handleServerErr(e) {
  }

  get(...args) {
    return new Promise(async (resolve, reject) => {
      this.showLoadingUI()
      try {
        let res = await super.get(...args)
        let isOk = this.handleRetError(res)
        if (isOk) {
          this.hideLoadingUI()
          resolve(res ? res.data : '')
        }
        let err = genErr(res)
        reject(err)
      } catch (err) {
        this.handleErr(err)
        reject(err)
      }
    })
  }

  post(...args) {
    return new Promise(async (resolve, reject) => {
      this.showLoadingUI()
      try {
        let res = await super.post(...args)
        let isOk = this.handleRetError(res)
        if (isOk) {
          this.hideLoadingUI()
          resolve(res ? res.data : '')
        }
        let err = genErr(res)
        reject(err)
      } catch (err) {
        this.handleErr(err)
        reject(err)
      }
    })
  }

  put(...args) {
    return new Promise(async (resolve, reject) => {
      this.showLoadingUI()
      try {
        let res = await super.put(...args)
        let isOk = this.handleRetError(res)
        if (isOk) {
          this.hideLoadingUI()
          resolve(res ? res.data : '')
        }
        let err = genErr(res)
        reject(err)
      } catch (err) {
        this.handleErr(err)
        reject(err)
      }
    })
  }

  delete(...args) {
    return new Promise(async (resolve, reject) => {
      this.showLoadingUI()
      try {
        let res = await super.delete(...args)
        let isOk = this.handleRetError(res)
        if (isOk) {
          this.hideLoadingUI()
          resolve(res ? res.data : '')
        }
        let err = genErr(res)
        reject(err)
      } catch (err) {
        this.handleErr(err)
        reject(err)
      }
    })
  }

  showLoadingUI() {
    if (this.navigationBarLoading) {
      wx.showNavigationBarLoading()
    }
    if (this.showLoading) {
      wx.showLoading({
        title: '正在加载',
      })
    }
  }

  hideLoadingUI() {
    if (this.navigationBarLoading) {
      wx.hideNavigationBarLoading()
    }
    if (this.showLoading) {
      wx.hideLoading()
    }
  }

  handleRetError(res) {
    console.d('res code', res, this.needHandleErr)
    if (!this.needHandleErr) {
      return true
    }
    let canGoNext = true
    if (res && res.data && res.data.code) {
      if (this.handleErrCode) {
        canGoNext = this.handleErrCode(res.data.code, res)
      }
    }
    if (canGoNext) {
      let err = new Error(
        res && res.data ? `${res.data.msg}` : 'server unknown error')
      let shouldHandleErr =
        this.shouldCatchErr ?
          this.shouldCatchErr(res) :
          (!res || !res.data || !res.data.code || res.data.code > 20000)
      if (shouldHandleErr) {
        this.handleErr(err, res)
        return false
      }
    }
    return true
  }

  handleErr(err, res) {
    console.error('handleErr', err)
    if (this.showError) {
      let message = err.message || err.msg || ''
      if (this.handleErrMessage) {
        this.handleErrMessage(message, err, res, config, this)
      }
    }
  }
}

export function initRequest(conf = {}) {
  return new CommonRequest(flyio, {
    base: '',
    ...conf,
  })
}

export let net = {}
net.encodeQueryData = function (data, encode = false) {
  let ret = []
  for (let d in data) {
    if (encode) {
      ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d]))
    } else {
      ret.push(d + '=' + data[d])
    }
  }
  return ret.join('&')
}


let _wx = {}

/**
 * 检测某个setting是否授权过
 *
 * @param key
 * @returns {Promise<any>}
 */
_wx.checkSettingAuthed = function (key) {
  return new Promise(resolve => {
    wxp.getSetting().then(res => {
      let ret = res.authSetting[_variable.AuthSetting[key]]
      resolve(ret)
    })
  })
}

/**
 * showToast
 *
 * @param title
 * @param icon
 * @param d
 */
_wx.showToast = function (title, icon = 'none', d = {}) {
  let opt = {
    title,
    icon,
    duration: 2000,
  }
  wx.showToast({
    ...opt,
    ...d,
  })
}

export let wxe = _wx

let _reg = {}
_reg.required = function (opt) {
  let d = {
    required: true,
  }
  return {
    ...d,
    ...opt,
  }
}
_reg.stringType = function (opt) {
  let d = {
    type: 'string',
    required: true,
  }
  return {
    ...d,
    ...opt,
  }
}
_reg.isOnlyHasNum = function (message = 'only can has num') {
  return {
    pattern: /^[0-9]+$/,
    message: 'only can has num ',
  }
}
_reg.isPhone = function (message = 'invalid phone') {
  return [
    {
      pattern: /^1[0-9]{10}$/,
      message: 'wrong phone format',
    },
  ]
}
_reg.lenRange = function (min = 0, max = 1, message = 'invalid range') {
  return function (rule, value, callback, source, options) {
    let errors = []
    let strValue = value + ''
    if (strValue.length < min || strValue.length > max) {
      errors.push(
        {
          message: `invalid range min:${min} max:${max}`,
          field: rule.field,
        },
      )
    }
    callback(errors)
  }
}

export let reg = _reg

export function simpleRequired(keys = []) {
  let ret = {}
  keys.forEach(key => {
    if (typeof key === 'string') {
      ret[key] = [
        _reg.required(),
      ]
    }
    if (Array.isArray(key)) {
      ret[key[0]] = key[1]
    }
  })
  return ret
}

/**
 * format url
 *
 * @param url
 * @param args
 * @example
 *
 * formatUrl('/student/course/:uuid/intention/', {
 *   uuid: 1
 * })
 * @returns {*}
 */
export function formatUrl(url, args = {}) {
  let a = url
  for (let k in args) {
    a = a.replace(new RegExp(`:(${k})+`, 'g'), args[k])
  }
  return a
}
